﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using StyleMVVM.Data;
using StyleMVVM.DependencyInjection;
using StyleMVVM.UnitTests.TestClasses.ValidationObjects;
using StyleMVVM.Utilities;
using StyleMVVM.Validation;
using StyleMVVM.Validation.Impl;
#if NETFX_CORE
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;

#else
using Microsoft.VisualStudio.TestTools.UnitTesting;

#endif

namespace StyleMVVM.UnitTests.Validation
{
	[TestClass]
	public class AttributeValidationProviderTests : BaseTestClass
	{
		[TestMethod]
		public void ProvideRulesTest()
		{
			AttributeValidationProvider provider = new AttributeValidationProvider();

			IReflectionService reflectionService = Container.Locate<IReflectionService>();
			IGlobalCache globalCache = Container.Locate<IGlobalCache>();

			provider.ImportDependencies(reflectionService, globalCache);

			IEnumerable<IValidationRule> rules = provider.ProvideRules(typeof(SimpleValidationObject), null);

			Assert.AreEqual(2, rules.Count());
		}

		[TestMethod]
		public void RequiresValidationRuleTest()
		{
			AttributeValidationProvider provider = new AttributeValidationProvider();

			IReflectionService reflectionService = Container.Locate<IReflectionService>();
			IGlobalCache globalCache = Container.Locate<IGlobalCache>();

			provider.ImportDependencies(reflectionService, globalCache);

			IEnumerable<IValidationRule> rules = provider.ProvideRules(typeof(SimpleValidationObject), null);

			Assert.AreEqual(2, rules.Count());

			ISyncValidationRule rule = rules.ElementAt(0) as ISyncValidationRule;

			Assert.IsNotNull(rule);

			SimpleValidationObject newSimpleObject = new SimpleValidationObject();

			RuleExecutionContext context = new RuleExecutionContext(newSimpleObject);

			// fix
			rule.Validate(context);

			Assert.AreEqual(ValidationState.InvalidRequired, context.State);
			Assert.AreEqual(1, context.ResultParts().Count());
			Assert.AreEqual("Name", context.ResultParts().ElementAt(0).PartName);

			newSimpleObject.Name = "Blah";

			context = new RuleExecutionContext(newSimpleObject);

			rule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);
		}

		[TestMethod]
		public void RangeValidationRuleTest()
		{
			AttributeValidationProvider provider = new AttributeValidationProvider();

			IReflectionService reflectionService = Container.Locate<IReflectionService>();
			IGlobalCache globalCache = Container.Locate<IGlobalCache>();

			provider.ImportDependencies(reflectionService, globalCache);

			IEnumerable<IValidationRule> rules = provider.ProvideRules(typeof(SimpleValidationObject), null);

			Assert.AreEqual(2, rules.Count());

			ISyncValidationRule rule = rules.ElementAt(1) as ISyncValidationRule;

			Assert.IsNotNull(rule);

			SimpleValidationObject newSimpleObject = new SimpleValidationObject();

			RuleExecutionContext context = new RuleExecutionContext(newSimpleObject);

			rule.Validate(context);

			Assert.AreEqual(ValidationState.Invalid, context.State);
			Assert.AreEqual(1, context.ResultParts().Count());
			Assert.AreEqual("TestInt", context.ResultParts().ElementAt(0).PartName);

			newSimpleObject.TestInt = 3;

			context = new RuleExecutionContext(newSimpleObject);

			rule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);
		}
	}
}